home *** CD-ROM | disk | FTP | other *** search
- {$c-}
- {$k-}
-
- {this program is a "stay resident" program which allows the operator to
- perform any of the last 10 commands which he had entered by entering an
- AltF10 to get a list of them, followed by a function key F1-F10
- to select which command to reenter. Command lines which begin with
- nonprintable keystrokes are not saved. This program was written as an example
- of a TurboPascal stay-resident program}
-
- {declare our constants}
-
- const
- our_char = 113; {this is the scan code for AltF10}
- scan_offset = 58; {scan code of F1 - 1}
- first_row = 5; {window size and position}
- first_col = 5;
- numb_saved = 10;
- windowwidth = 40;
- windowlength = 12; {=numb_saved + 2}
- CR = $D;
- user_int = $68; {place to put out interrupt}
- kybrd_int = $16; {BIOS keyboard interrupt}
- prog_size = 16000; {approximate size of program --
- this much space is reserved upon exit}
-
- {here the global (static type) variables}
-
- type
- regtype = record
- ax,bx,cx,dx,bp,si,di,ds,es,flags:integer
- end;
- halfregtype = record
- al,ah,bl,bh,cl,ch,dl,dh:byte
- end;
-
- const {pur 'regs' in the code segment}
- regs : regtype = (ax:0;bx:0;cx:0;dx:0;bp:0;si:0;di:0;ds:0;es:0;flags:0);
- feeding_char :boolean = FALSE;
- no_cr :boolean = FALSE;
- j :integer = 1;
- saveds :integer = 0;
-
- var
- savreg :regtype; {define a variable for the structures}
- halfregs :halfregtype absolute regs; {and for the half registers}
-
- i :integer;
- last_lines :array [0..numb_saved] of array[1..60] of integer;
- cursorpos :integer;
- {.pa}
- {include the window manipulation software}
- {$i lastwin.inc}
- {.pa}
- {the following code prints out the previous n commands in
- the window previously opened up}
-
- procedure printchoices;
- var
- i,j : integer;
- outchar : byte;
-
- begin
- for i := 2 to numb_saved+1 do {loop thru the saved commands}
- begin
- GoToXY(2,i);
- Write('F');Write(((i-1) mod 10):1);Write(')'); {put up the command number}
- j := 1;
- while ((last_lines[i-1][j] and $FF) <> CR) and (j <> (windowwidth-5)) do
- begin
- Write(Chr(last_lines[i-1][j] and $FF));
- j := j + 1
- end
- end
- end;
- {.pa}
- {this code processes interrupts to the get_char BIOS interrupt}
-
- procedure process_intr;
- begin;
- {$i lastsave.inc} {save the input registers}
- if halfregs.ah = 0 then {if this is character request...}
- begin
- if feeding_char then {if we were in the middle of spooling chars...}
- begin
- regs.ax := last_lines[i][j]; {...fetch the next character...}
- j := j + 1;
- if (halfregs.al = CR) or (j > 60) then {...if this was the last character...}
- begin
- feeding_char := false; {...turn spooling off}
- j := 1;
- if no_cr then
- regs.ax := $0;
- no_cr := false
- end
- end
- else
- begin {(we are not in the middle of spooling)}
- Intr (user_int, regs); {perform the BIOS call}
- if halfregs.ah <> our_char then {if this wasn't "our" character...}
- begin
- last_lines[0][j] := regs.ax; {...save the keystroke...}
- if j < 60 then
- j := j + 1;
- if halfregs.al = CR then {...if that was a cr...}
- begin
- j := 1; {...pop down to next entry...}
- if Lo(last_lines[0][1]) <> 0 then {...if the first char was printable...}
- for i := numb_saved downto 1 do
- last_lines[i] := last_lines[i-1];
- for i := 1 to 60 do {...clear last entry}
- last_lines[0][i] := $07 shl 8 + CR
- end
- end
- else
- begin
- savreg.ax := $0300; {fetch the current cursor position}
- savreg.bx := $0;
- Intr($10,savreg);
- cursorpos := savreg.dx;
-
- openwindow; {open up the display window}
- printchoices; {now print the last commands}
- regs.ax := $0; {read a character from the keyboard}
- Intr(user_int,regs);
-
- i := halfregs.ah - scan_offset; {note that 0 maps to 1}
- if (i > 25) and (i < 37) then
- begin
- i := i - 25;
- no_cr := true
- end;
- if (i > 0) and (i <= 10) then
- begin {legal input}
- regs.ax := last_lines[i][1]; {give him the first char}
-
- if halfregs.al <> CR then
- begin
- feeding_char := true;
- j := 2
- end;
-
- end;
- closewindow; {put what was there back}
-
- savreg.ax := $0200; {reposition cursor}
- savreg.bx := $0;
- savreg.dx := cursorpos;
- Intr($10,savreg)
- end
- end
- end
- else {he's not trying t read a character}
- if feeding_char then {if he's spooling characters...}
- regs.flags := regs.flags and $FFBF {...clear the zero bit}
- else
- Intr(user_int,regs);
-
- {$i lastrstr.inc} {restore the registers from 'reg'}
- inline($CA/$02/$00) {RETF 02}
- end;
- {.pa}
- {this section of code installs the interrupt routine and makes it permanently
- resident interrupt borrower}
-
- {the following dos calls are used:
- sys 25- install interrupt address
- input al = int number, ds:dx = address to install
-
- sys 35- get interrupt address
- input al = int number
- output es:bx = address in interrupt
-
- int 27- terminate and stay resident
- input dx = size of resident program
- }
- begin {**main**}
- {initialize the variables which the interrupt service routine will use}
-
- for i := 0 to numb_saved do
- for j := 1 to 60 do
- last_lines[i][j] := $07 shl 8 + CR;
- j := 1;
- saveds := Dseg; {save the data segment locally}
-
- {now install the interrupt routine}
-
- savreg.ax := $35 shl 8 + user_int; {check to make sure int not already used}
- Intr($21,savreg);
- if savreg.es <> $00 then
- WriteLn ('Interrupt in use -- cant install LASTCOMMAND')
- else
- begin
- WriteLn ('Installing LASTCOMMAND -- press AltF10 to select last command');
-
- savreg.ax := $35 shl 8 + kybrd_int;{get the address that was there}
- Intr($21,savreg);
-
- savreg.ax := $25 shl 8 + user_int; {put the address in the user interrupt}
- savreg.ds := savreg.es;
- savreg.dx := savreg.bx;
- Intr($21,savreg);
-
- savreg.ax := $25 shl 8 + kybrd_int;{install interrupt system call}
- savreg.ds := cseg;
- savreg.dx := Ofs(process_intr); {put our routine address}
- Intr ($21,savreg);
-
- {now terminate and stay resident}
-
- savreg.dx := prog_size;
- Intr ($27,savreg)
- end
- end.